﻿using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids;
using Volo.Abp.Identity;
using Volo.Abp.PermissionManagement;
using YaAppoint.CustomSettings;
using YaAppoint.DapperRepositories;
using YaAppoint.Permissions;
using YaAppoint.PrintTemplates;
using YaAppoint.TextTemplates;

namespace YaAppoint
{
    public class GlobalCustomSettingSeedContributor(IRepository<CustomSetting,Guid> settingRepository,
                                                    IRepository<IdentityRole,Guid> roleRepository,
                                                    IRepository<TextTemplate,Guid> textTempalteRepository,
                                                    IRepository<PermissionGrant,Guid> permissionGrantRepository,
                                                    IGuidGenerator guidGenerator,
                                                    IConfiguration configuration) : IDataSeedContributor, ITransientDependency
    {
        private readonly IRepository<CustomSetting, Guid> _settingRepository = settingRepository;
        private readonly IConfiguration _configuration = configuration;
        private readonly IRepository<IdentityRole, Guid> _roleRepository = roleRepository; 
        private readonly IRepository<PermissionGrant, Guid> _permissionGrantRepository= permissionGrantRepository;
        private readonly IGuidGenerator _guidGenerator = guidGenerator;
        private readonly IRepository<TextTemplate, Guid> _textTempalteRepository= textTempalteRepository;


        public async Task SeedAsync(DataSeedContext context)
        {
            // 播种全局默认设置
            await SeedGlobalSetting();

            // 播种在线服务
            await SeedOnLineService();


            // 播种科室管理员角色
            await SeedDepartmentAdminRole();

            // 播种住院预约角色
            await SeedInpatientRole();
        }


        /// <summary>
        /// 播种全局设置
        /// (根据配置文件)
        /// </summary>
        /// <returns></returns>
        public async Task SeedGlobalSetting()
        {
            var list = await _settingRepository.GetListAsync(s => s.Level == SettingLevel.Global);
            if (list.Count == 1)
            {
                return;
            }
            else if (list.Count > 1)
            {
                await _settingRepository.DeleteAsync(gs => gs.Level == SettingLevel.Global);
            }
            var golbalSetting = new CustomSetting();
            golbalSetting.Level = SettingLevel.Global;
            golbalSetting.AppointableCount = Convert.ToInt32(_configuration["GlobalCustomSetting:AppointableCount"]);
            golbalSetting.AutoAppointableCount = Convert.ToInt32(_configuration["GlobalCustomSetting:AutoAppointableCount"]);
            golbalSetting.Earliest = Convert.ToInt32(_configuration["GlobalCustomSetting:Earliest"]);
            golbalSetting.CheckInMode = (CheckInMode)Convert.ToInt32(_configuration["GlobalCustomSetting:CheckInMode"]);
            golbalSetting.LatestAppoint = Convert.ToInt32(_configuration["GlobalCustomSetting:LatestAppoint"]);
            golbalSetting.UnpaidWillBeCancel = Convert.ToBoolean(_configuration["GlobalCustomSetting:UnpaidWillBeCancel"]);
            golbalSetting.UnpaidTimeLimit = Convert.ToInt32(_configuration["GlobalCustomSetting:UnpaidTimeLimit"]);

            await _settingRepository.InsertAsync(golbalSetting);
        }

        /// <summary>
        /// 角色播种
        /// (科室管理员)
        /// </summary>
        /// <returns></returns>
        public async Task SeedDepartmentAdminRole()
        {
            var exisitingRole = await _roleRepository.FirstOrDefaultAsync(r => r.Name == "科室管理员");
            if (exisitingRole == null)
            {
                var role = new IdentityRole(_guidGenerator.Create(), "科室管理员")
                {
                    ConcurrencyStamp = _guidGenerator.Create().ToString(),
                    IsStatic = true,// 系统内置角色（不可删除）
                    IsDefault = false,// 非默认角色 (新用户不自动分配)
                    IsPublic = true  // 公开角色，前端可展示选择
                };
                await _roleRepository.InsertAsync(role, autoSave: true);//立刻新建

                List<string> roleNameList = new List<string>();

                #region 基础管理
                // 检查项目权限
                roleNameList.Add(YaAppointPermissions.ExamItems.Default);
                roleNameList.Add(YaAppointPermissions.ExamItems.Add);
                roleNameList.Add(YaAppointPermissions.ExamItems.Edit);
                roleNameList.Add(YaAppointPermissions.ExamItems.Delete);
                roleNameList.Add(YaAppointPermissions.ExamItems.Sync);

                // 科室用户管理
                roleNameList.Add(YaAppointPermissions.DepartmentUsers.Default);
                roleNameList.Add(YaAppointPermissions.DepartmentUsers.Add);
                roleNameList.Add(YaAppointPermissions.DepartmentUsers.Remove);
                roleNameList.Add(YaAppointPermissions.DepartmentUsers.CreateDepartmentUser);
                #endregion

                #region 设备管理
                // 科室设备类型
                roleNameList.Add(YaAppointPermissions.DeparmentDeviceTypes.Default);
                roleNameList.Add(YaAppointPermissions.DeparmentDeviceTypes.Add);
                roleNameList.Add(YaAppointPermissions.DeparmentDeviceTypes.Remove);
                roleNameList.Add(YaAppointPermissions.DeparmentDeviceTypes.Create);

                // 设备管理
                roleNameList.Add(YaAppointPermissions.Devices.Default);
                roleNameList.Add(YaAppointPermissions.Devices.Add);
                roleNameList.Add(YaAppointPermissions.Devices.Edit);
                roleNameList.Add(YaAppointPermissions.Devices.Delete);

                // 诊室管理
                roleNameList.Add(YaAppointPermissions.Rooms.Default);
                roleNameList.Add(YaAppointPermissions.Rooms.Add);
                roleNameList.Add(YaAppointPermissions.Rooms.Edit);
                roleNameList.Add(YaAppointPermissions.Rooms.Delete);


                #endregion

                #region 诊室排班管理
                // 排班表管理
                roleNameList.Add(YaAppointPermissions.Schedules.Default);
                roleNameList.Add(YaAppointPermissions.Schedules.Create);
                roleNameList.Add(YaAppointPermissions.Schedules.Edit);
                roleNameList.Add(YaAppointPermissions.Schedules.Delete);
                roleNameList.Add(YaAppointPermissions.Schedules.Disable);

                // 排班表时间段管理
                roleNameList.Add(YaAppointPermissions.TimeIntervals.Default);
                roleNameList.Add(YaAppointPermissions.TimeIntervals.Create);
                roleNameList.Add(YaAppointPermissions.TimeIntervals.BatchCreate);
                roleNameList.Add(YaAppointPermissions.TimeIntervals.Delete);
                roleNameList.Add(YaAppointPermissions.TimeIntervals.Edit);
                roleNameList.Add(YaAppointPermissions.TimeIntervals.Disable);

                // 排班表号池计划管理
                roleNameList.Add(YaAppointPermissions.PlanPools.Default);
                roleNameList.Add(YaAppointPermissions.PlanPools.Create);
                roleNameList.Add(YaAppointPermissions.PlanPools.Delete);
                roleNameList.Add(YaAppointPermissions.PlanPools.Edit);
                roleNameList.Add(YaAppointPermissions.PlanPools.BatchCreate);
                roleNameList.Add(YaAppointPermissions.PlanPools.Disable);
                roleNameList.Add(YaAppointPermissions.PlanPools.Clear);

                // 号池管理
                roleNameList.Add(YaAppointPermissions.Pools.Default);
                roleNameList.Add(YaAppointPermissions.Pools.AddAppoint);
                roleNameList.Add(YaAppointPermissions.Pools.Cancel);

                // 特殊排班管理
                roleNameList.Add(YaAppointPermissions.ScheduleOverrides.Default);
                roleNameList.Add(YaAppointPermissions.ScheduleOverrides.Create);
                roleNameList.Add(YaAppointPermissions.ScheduleOverrides.Delete);
                roleNameList.Add(YaAppointPermissions.ScheduleOverrides.Edit);
                roleNameList.Add(YaAppointPermissions.ScheduleOverrides.Disable);

                // 预约设置
                roleNameList.Add(YaAppointPermissions.CustomSetting.Default);
                roleNameList.Add(YaAppointPermissions.CustomSetting.Edit);
                roleNameList.Add(YaAppointPermissions.CustomSetting.Disable);
                #endregion

                // 科室预约
                roleNameList.Add(YaAppointPermissions.ManulaAppoints.Default);

                // 科室签到
                roleNameList.Add(YaAppointPermissions.CheckIn.Default);

                List<PermissionGrant> grantList = new List<PermissionGrant>();
                foreach (var name in roleNameList)
                {
                    var isGranted = await _permissionGrantRepository.FirstOrDefaultAsync(g => g.Name == name
                                                                                                && g.ProviderKey == "科室管理员"
                                                                                                && g.ProviderName == "R");
                    if (isGranted == null)
                    {
                        var permissionGrant = new PermissionGrant(
                         id: _guidGenerator.Create(),
                         name: name,
                         providerName: "R", // 角色权限
                         providerKey: "科室管理员" // 角色ID的字符串形式(ABP 存储规范)
                        )
                        {

                        };
                        grantList.Add(permissionGrant);
                    }
                }
                await _permissionGrantRepository.InsertManyAsync(grantList);
            }
        }

        /// <summary>
        /// 住院角色播种
        /// </summary>
        /// <returns></returns>
        public async Task SeedInpatientRole()
        {
            var exisiting = await _roleRepository.FirstOrDefaultAsync(r => r.Name == "住院预约");
            if (exisiting == null)
            {
                var role = new IdentityRole(_guidGenerator.Create(), "住院预约")
                {
                    ConcurrencyStamp = _guidGenerator.Create().ToString(),
                    IsStatic = true,   // 系统内置角色
                    IsDefault = false, // 非默认角色 (新用户不自动分配)
                    IsPublic = true     // 公开角色，前端可展示选择
                };
                await _roleRepository.InsertAsync(role, autoSave: true);//立刻新建
                List<string> permissionNameList = new List<string>();
                permissionNameList.Add(YaAppointPermissions.InPatientAppoints.Defalut);
                List<PermissionGrant> grantList = new List<PermissionGrant>();
                foreach (var permission in permissionNameList)
                {
                    var isGranted = await _permissionGrantRepository.FirstOrDefaultAsync(g => g.Name == permission
                                                                                            && g.ProviderKey == "住院预约"
                                                                                            && g.ProviderName == "R");
                    if (isGranted == null)
                    {
                        var permissionGrant = new PermissionGrant(
                            id: _guidGenerator.Create(),
                            name: permission,
                            providerKey:"住院预约",
                            providerName: "R"
                        );

                        grantList.Add(permissionGrant);
                    }
                }
                await _permissionGrantRepository.InsertManyAsync(grantList);
            }
        }

        /// <summary>
        /// 在线服务播种
        /// </summary>
        /// <returns></returns>
        public async Task SeedOnLineService()
        {
            List<TextTemplate> onLineServiceList = new List<TextTemplate>();

            // ApplyItemMapService   （从his获取检查项目的额外映射服务）
            var service1 = await _textTempalteRepository.FirstOrDefaultAsync(t => t.Type == TemplateType.Service && t.Interface == "IApplyItemMapService");
            if (service1 == null)
            {
                var applyItemMapService = new TextTemplate();
                applyItemMapService.Interface = "IApplyItemMapService";
                applyItemMapService.Name = "his申请项目到本地申请项目的额外映射转换服务";
                applyItemMapService.Type = TemplateType.Service;
                applyItemMapService.IsActive = true;
                applyItemMapService.TypeName = "YaAppoint.DapperRepositories.ApplyItemMapService";
                applyItemMapService.Content = "using Microsoft.Extensions.Configuration;\r\nusing Volo.Abp.DependencyInjection;\r\n\r\nnamespace YaAppoint.DapperRepositories\r\n{\r\n    public class ApplyItemMapService(IConfiguration configuration) : IApplyItemMapService, ITransientDependency\r\n    {\r\n        private readonly IConfiguration _configration = configuration;\r\n\r\n        public void ExtraConvert(HisExamApplyItemDto hisDto, ExamApplication entity)\r\n        {\r\n           // 此处对配置额外的转换\r\n        }\r\n    }\r\n}";

                onLineServiceList.Add(applyItemMapService);
            }

            // ApplySearchConfigService (his申请项目查询时额外的条件配置服务)
            var service2 = await _textTempalteRepository.FirstOrDefaultAsync(t => t.Type == TemplateType.Service && t.Interface == "IApplySearchConfigService");
            if (service2 == null)
            {
                var applySearchConfigService = new TextTemplate();
                applySearchConfigService.Interface = "IApplySearchConfigService";
                applySearchConfigService.Name = "查询his申请项目视图配置服务";
                applySearchConfigService.Type = TemplateType.Service;
                applySearchConfigService.IsActive = true;
                applySearchConfigService.TypeName = "YaAppoint.ExamApplies.ApplySearchConfigService";
                applySearchConfigService.Content = "using Microsoft.Extensions.Configuration;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing Volo.Abp;\r\nusing Volo.Abp.Application.Services;\r\nusing Volo.Abp.DependencyInjection;\r\nusing YaAppoint.ExamAppies;\r\n\r\nnamespace YaAppoint.ExamApplies\r\n{\r\n    [RemoteService(isEnabled: false)]\r\n    public class ApplySearchConfigService(IConfiguration configuration) : ApplicationService, IApplySearchConfigService, ITransientDependency\r\n    {\r\n\r\n        private IConfiguration _configuration = configuration;\r\n\r\n\r\n        public Func<Dictionary< string, object>, string,string>? GetAddCondition()\r\n        {\r\n            return ConfigExtraCondition;\r\n        }\r\n\r\n        // 配置额外条件\r\n        private string ConfigExtraCondition(Dictionary<string, object> userData,string condition)\r\n        {\r\n            return condition;\r\n        }\r\n\r\n        public Func<string>? GetSearchNumber()\r\n        {\r\n            return () =>\r\n            {\r\n                return $@\" and (IdCardNumber=@number or CONVERT(varchar(1000),MedicalCardNumber)=@number or  PhoneNumber=@number or PhysicalExamNumber=@number \r\n               or OutPatientNumber=@number or InPatientNumber=@number or ApplyNumber=@number or Name=@number)\";\r\n            };\r\n        }\r\n    }\r\n}";

                onLineServiceList.Add(applySearchConfigService);
            }

            // CheckInByApi (通过pacs或者叫号系统的api 进行签到)
            var service3 = await _textTempalteRepository.FirstOrDefaultAsync(t => t.Type == TemplateType.Service && t.Interface == "ICheckInByApi");
            if (service3 == null)
            {
                var checkInByApi = new TextTemplate();
                checkInByApi.Interface = "ICheckInByApi";
                checkInByApi.Name = "调用pacs/叫号系统接口签到";
                checkInByApi.Type = TemplateType.Service;
                checkInByApi.IsActive = true;
                checkInByApi.TypeName = "YaAppoint.Appointments.CheckIn.CheckInByApi";
                checkInByApi.Content = "using System;\r\nusing System.Collections.Generic;\r\nusing System.Net.Http;\r\nusing System.Threading.Tasks;\r\nusing Volo.Abp.Domain.Repositories;\r\nusing Volo.Abp.Json;\r\nusing YaAppoint.Response;\r\n\r\nnamespace YaAppoint.Appointments.CheckIn\r\n{\r\n\r\n    /// <summary>\r\n    /// 服务模板\r\n    /// 通过API签到r\r\n    /// </summary>\r\n    public class CheckInByApi : ICheckInByApi\r\n    {\r\n        private readonly IHttpClientFactory _httpClientFactory;\r\n        private readonly HttpClient _httpClient;\r\n        private readonly IJsonSerializer _jsonSerializer;\r\n        private readonly IRepository<Appointment, Guid> _appointmentRepository;\r\n\r\n        public CheckInByApi(IHttpClientFactory httpClientFactory,\r\n                            IJsonSerializer jsonSerializer,\r\n                            IRepository<Appointment, Guid> appointmentRepository)\r\n        {\r\n            _httpClientFactory = httpClientFactory;\r\n            _httpClient = _httpClientFactory!.CreateClient();\r\n            _httpClient.BaseAddress = new Uri(\"https://www.baidu.com\");\r\n            _jsonSerializer = jsonSerializer;\r\n            _appointmentRepository = appointmentRepository;\r\n        }\r\n\r\n        /// <summary>\r\n        /// 批量自动签到\r\n        /// </summary>\r\n        /// <param name=\"appointNumbers\"></param>\r\n        /// <returns></returns>\r\n        /// <exception cref=\"NotImplementedException\"></exception>\r\n        public async Task<BackJson> BatchCheckInAsync(List<string> appointNumbers)\r\n        {\r\n            return new BackJson();\r\n        }\r\n\r\n        /// <summary>\r\n        /// 单个签到\r\n        /// </summary>\r\n        public async Task<RomoteCheckInRes> CheckInAsync(string appointNumber)\r\n        {\r\n            //try\r\n            //{\r\n            //    // 数据序列化\r\n            //    var content = new StringContent(\r\n            //        _jsonSerializer.Serialize(appointIds),\r\n            //        Encoding.UTF8,\r\n            //        \"application/json\"); //媒体类型\r\n\r\n            //    // 发送请求\r\n            //    var response = await _httpClient.PostAsync(\"/api/check-in\", content);\r\n\r\n            //    var pacsRes = await  response.Content.ReadFromJsonAsync<BackJson>();\r\n            //    if (pacsRes.code == 0)\r\n            //    {\r\n            //        var list = await _appointmentRepository.GetListAsync(a => appointIds.Contains(a.Id));\r\n            //        foreach (var appoint in list)\r\n            //        {\r\n            //            appoint.Status = AppointmentStatus.Achieve;\r\n            //        }\r\n            //        return new BackJson\r\n            //        {\r\n            //            code = 0,\r\n            //            data = pacsRes.data\r\n            //        };\r\n            //    }\r\n            //    else\r\n            //    {\r\n            //        return new BackJson\r\n            //        {\r\n            //            code = pacsRes.code,\r\n            //            err = pacsRes.err\r\n            //        };\r\n            //    }\r\n            //}\r\n            //catch (Exception ex)\r\n            //{\r\n            //    throw new BusinessException(message:ex.Message);\r\n            //}\r\n            #region 模拟数据 \r\n            List<RomoteCheckInRes> resList = new List<RomoteCheckInRes>();\r\n            var res = new RomoteCheckInRes();\r\n            res.Succeed = true;\r\n            res.AppointNumber = appointNumber;\r\n            res.QueueData = new\r\n            {\r\n                number = appointNumber,\r\n                queque = \"01\",\r\n                room= \"DR1室\",\r\n                name= \"张三\",\r\n                phone=\"18914894368\"\r\n            };\r\n            return res;\r\n            #endregion\r\n        }\r\n\r\n        /// <summary>\r\n        /// 重新打印\r\n        /// </summary>\r\n        public async Task<BackJson> Reprint(string appointNumber)\r\n        {\r\n            return new BackJson();\r\n        }\r\n    }\r\n}\r\n";
                onLineServiceList.Add(checkInByApi);
            }

            // WriteBackToHisService (回写到His)
            var service4 = await _textTempalteRepository.FirstOrDefaultAsync(t => t.Type == TemplateType.Service && t.Interface == "IWriteBackToHisService");
            if (service4==null)
            {
                var writeBackToHisService = new TextTemplate();
                writeBackToHisService.Interface = "IWriteBackToHisService";
                writeBackToHisService.Name = "回写到his服务";
                writeBackToHisService.Type = TemplateType.Service;
                writeBackToHisService.IsActive = true;
                writeBackToHisService.TypeName = "YaAppoint.Appointments.WriteBackToHisService";
                writeBackToHisService.Content= "using System;\r\nusing System.Collections.Generic;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace YaAppoint.Appointments\r\n{\r\n    public class WriteBackToHisService : IWriteBackToHisService\r\n    {\r\n        public void WiteBack(List<ApplyExamItemStatusChangeDto> dtos)\r\n        {\r\n            Console.WriteLine(\"已经回写到his\");\r\n\r\n            // 此处添加回写逻辑；\r\n            return;\r\n        }\r\n\r\n        public async Task WiteBackAsync(List<ApplyExamItemStatusChangeDto> dtos)\r\n        {\r\n            // 此处添加回写逻辑\r\n            Console.WriteLine(\"已经回写his\");\r\n            return;\r\n        }\r\n    }\r\n}";

                onLineServiceList.Add(writeBackToHisService);
            }
            await _textTempalteRepository.InsertManyAsync(onLineServiceList);
        }

        /// <summary>
        /// 播种打印字段配置
        /// </summary>
        /// <returns></returns>
        public async Task SeedPrintFieldsTemplate()
        { 
            List<TextTemplate> printFieldsList = new List<TextTemplate>();

            // 预约凭证打印字段配置json
            var fields1 = await _textTempalteRepository.FirstOrDefaultAsync(t => t.Name.Contains("预约小票打印字段JSON")
                                                                                 && t.Type==TemplateType.Json);
            if (fields1 == null)
            {
                fields1 = new TextTemplate();
                fields1.Name = "预约小票打印字段JSON";
                fields1.Type = TemplateType.Json;
                fields1.Content = "[\r\n    {field:'name',text:'姓名'},\r\n    {field:'number',text:'预约编号'}\r\n    {field:'examItems',text:'申请项目'}\r\n]";
                printFieldsList.Add(fields1);
            }

            // 签到凭证打印字段配置Json
            var fields2 = await _textTempalteRepository.FirstOrDefaultAsync(t => t.Name.Contains("签到小票打印字段Json")
                                                                               && t.Type == TemplateType.Json);
            if (fields2 == null)
            {
                fields2 = new TextTemplate();
                fields2.Name = "签到小票打印字段Json";
                fields2.Type = TemplateType.Json;
                fields2.Content = "[\r\n    {field:'name',text:'姓名'},\r\n    {field:'queueNumber',text:'队列序号'}\r\n]";
                printFieldsList.Add(fields2);
            }
            await _textTempalteRepository.InsertManyAsync(printFieldsList);
        }
    }
}
